#pragma once
#include<vector>
#include"sem.hpp"
#include<pthread.h>


template <class T>
class RingQueue
{   
public:
    RingQueue(int capacity = 5)
    :_capacity(capacity)
    ,_blank(capacity)
    ,_data(0)
    ,_pstep(0)
    ,_cstep(0)
    ,_v(capacity)
    {
        pthread_mutex_init(&_pmutex,nullptr);
        pthread_mutex_init(&_cmutex,nullptr);
    }

    ~RingQueue()
    {
        pthread_mutex_destroy(&_pmutex);
        pthread_mutex_destroy(&_cmutex);
    }

    void EQueue(const T& in)
    {
        //生产者
        _blank.P();
        pthread_mutex_lock(&_pmutex);
        _v[_pstep++] = in;
        _pstep %= _capacity;
        pthread_mutex_unlock(&_pmutex);
        _data.V();
    }

    void PQueue(T* out)
    {
        //消费者
        _data.P();
        pthread_mutex_lock(&_cmutex);
        *out = _v[_cstep++];
        _cstep %= _capacity;
        pthread_mutex_unlock(&_cmutex);
        _blank.V();
    }

private:
    std::vector<T> _v;
    Sem _blank;
    Sem _data;
    pthread_mutex_t _pmutex;
    pthread_mutex_t _cmutex;
    int _capacity;
    int _pstep;
    int _cstep;
};